﻿/*****************************************************************
 * @file sys.c
 * @author ShiHongChao
 * @brief here are globally-called functions, global hooks or weak functions,
 *        global configurations.
 *****************************************************************
 */

#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"
#include "systick.h"
#include "debug.h"


INIT_BSP_START();
INIT_BSP_END();


/**
 * 系统初始化
 */
void SysInit(void)
{
    /*
        To prevent interrupt service program execution when initializing STM32
        peripherals before starting scheduling, here disable global interrupt.

        the benefits of this are:
        1. prevent interrupt service programs that call the FreeRTOS API executing
           before starting the scheduler.
        2. make sure the system normally start and is not affected by other interrupts.

        function prvStartFirstTask of in the transplant file port.c will be restart
        global interrupt, so don't worry.
     */
    __disable_irq();

    /* configure interrupt priority group to 4 */
    nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
    /* configure systick */
    systick_init();

    /* bsp initialize */
    extern void BspInit(void);
    BspInit();
}

/**
 * @brief idle taske hook
 * @param None
 */
void vApplicationIdleHook(void)
{
    extern TaskHandle_t keyTaskHandle;
    extern TaskHandle_t LcdTaskHandle;

    #ifdef DEBUG

    // log("[info] lcdTask remaning stack %u\n", uxTaskGetStackHighWaterMark(LcdTaskHandle));
    // log("[info] keyTask remaning stack %u\n", uxTaskGetStackHighWaterMark(keyTaskHandle));

    #endif // DEBUG
}

/**
 * @brief mian任务入口函数
 */
void MainEntery(void *parameter)
{
    log("[info] main task start\n");

    /* 返回执行 mian函数 */
    extern int $Super$$main(void);
    $Super$$main();
}

/**
 * @brief main函数补丁函数(armcc扩展) 在调用main之前调用补丁函数
 * @fn 创建main任务
 */
int $Sub$$main(void)
{
    SysInit();

    /* create main task */
    TaskHandle_t mainHandle = NULL;
    xTaskCreate(MainEntery, "main", 512, NULL, 1, &mainHandle);
    configASSERT(NULL != mainHandle);

    /* setup scheduler */
    vTaskStartScheduler();

    return 0;
}
